﻿#define _CRT_SECURE_NO_WARNINGS
// ↑ 将本行在代码放在第一行可以避免 scanf的报错问题（仅在VS编译器里）
//【学习记录】
//【初阶】25.单链表实现
//【初阶】26.休息
//【初阶】27.单链表实现
//【初阶】28.OJ题练习（待补充）




//【头文件包含】

#include"SingleList.h"


//【结构声明】	


//【函数声明】
void TestSingleList1();//单链表接口函数测试用例
SGLN* removeElements(SGLN* head, int val);
void TestSingleList2();


//【主函数】
int main()
{
	TestSingleList1();

	//OJ题目练习1
	{
		printf("练习1:给一个链表的头结点head,和一个整数val，删除链表所满足得Node.val == val的节点并返回新节点\n");
		TestSingleList2();
		printf("\n");
	}
	return 0;
}

//【函数】

void TestSingleList1()//单链表接口函数测试用例
{
	SGLN* plist=NULL;
	SGLN** pplist = plist;
	//初始化
	//SingleListInit(&sl);
	//尾插
	SingleListPushBack(&plist, 1);
	SingleListPushBack(&plist, 2);
	SingleListPushBack(&plist, 3);
	SingleListPushBack(&plist, 4);
	SingleListPushBack(&plist, 5);
	SingleListPrint(plist);
	//尾删
	SingleListPopBack(&plist);
	SingleListPrint(plist);
	//头插
	SingleListPushFront(&plist, 2);
	SingleListPrint(plist);
	//头删
	SingleListPopFront(&plist);
	SingleListPrint(plist);
	//查找元素
	SingleListPrint(SingleListFind(plist, 3));
	SingleListInsert(&plist, SingleListFind(plist, 3), 10);
	SingleListPrint(plist);
	SingleListInsert(&plist, SingleListFind(plist, 1), 10);
	SingleListPrint(plist);
}
SGLN* removeElements(SGLN* head, int val)
{
	SGLN* cur = head;
	SGLN* curbefor = NULL;

	while (cur != NULL)
	{

		if (cur->data != val)
		{
			curbefor = cur;
			cur = cur->next;
		}
		else
		{
			if (curbefor == NULL)
			{
				head = cur->next;
				free(cur);
				cur = head;
			}
			else
			{
				curbefor->next = cur->next;
				free(cur);
				cur = curbefor->next;
			}
		}
	}
	return head;
}
void TestSingleList2()
{
	{
		SGLN* plist = NULL;
		SGLN** pplist = plist;
		//初始化
		//SingleListInit(&sl);
		//尾插
		SingleListPushBack(&plist, 1);
		SingleListPushBack(&plist, 2);
		SingleListPushBack(&plist, 6);
		SingleListPushBack(&plist, 3);
		SingleListPushBack(&plist, 4);
		SingleListPushBack(&plist, 5);
		SingleListPushBack(&plist, 6);
		SingleListPrint(plist);

		plist = removeElements(plist, 6);
		SingleListPrint(plist);
	}
	{
		SGLN* plist = NULL;
		SGLN** pplist = plist;
		SingleListPushBack(&plist, 6);
		SingleListPushBack(&plist, 6);
		SingleListPushBack(&plist, 6);
		SingleListPrint(plist);

		plist = removeElements(plist, 6);
		SingleListPrint(plist);

		printf("销毁单链表空间\n");
		SingleListDestory(&plist);
		printf("打印检查\n");
		SingleListPrint(plist);
	}


}

//【笔记】
//25.单链表实现
//27.单链表实现
	//单链表弊端
		// 每个数据都要存一个指针去链接后面的数据节点
		// 不支持随机访问
		// 单纯的单链表增删查改意义不大
		// 单链表更多是做更复杂数据结构的子结构，如哈希桶、邻接表
		// 链表存储数据更应该使用双向链表
	//void SingleListPrint(SGLN* phead);//单链表打印
		//先创建一个结构体参数，把传递的结构体指针赋值给它
		// 循环判断地址是否为空，不为空则打印该指针下的结构体存放元素的成员，
		// 然后将结构体存放下一个指针的成员赋值给被判断的地址
		// 直到为空，跳出循环。
	//SGLN* SingleListNewMember(SGLDataType x);//单链表创建新成员
		//因为头插尾插都要开辟一块新空间并将新成员值赋给这个空间的元素成员，所以将该功能封装成一个函数，
		// malloc一个结构体大小空间，指向结构体类型指针，值赋给新结构体元素成员，新结构体地址成员置空
		// 将新结构体指针返回
	//void SingleListPushBack(SGLN** pphead, SGLDataType x);//单链表尾部插入
		//先开辟一个结构体空间，将值赋给结构体的元素成员、指针成员指向空指针
		//判断传递的指针的指针指向的位置是否为空，为空则将该空间赋给第一个结构体	
		//否则从首个结构体开始查找，判断指针成员是否为空，直到成立，则将开辟空间地址赋给该空指针成员
	//void SingleListPopBack();//单链表尾部删除
		// 先判断传递的指针指向的位置是否为空，为空则不执行
		// 否则从首个结构体开始查找，判断指针成员是否为空，直到成立
		// 前一结构体指针成员指向空指针
		// 将该结构体空间释放
		// 另外还要分情况，如果只有一个元素的时候即一上来如果找到的就是唯一的成员则只删除不前一个置空
	//void SingleListPushFront();//单链表头部插入
		//先开辟一个结构体空间，将值赋给结构体的元素成员、指针成员指向空指针
		//判断传递的指针的指针指向的位置是否为空，为空则将该空间赋给第一个结构体
		//否则将开辟结构体空间指针成员赋值 链表头部地址
	//void SingleListPopFront();//单链表头部删除
		//先判断传递的指针指向的位置是否为空，为空则不执行
		//否则先创建一个临时变量赋值首个结构体地址
		//再将首个结构体的指针成员赋值给首个结构体的指针
		//再通过临时变量释放原来首个结构体开辟的空间
	//void SingleListInsert();//单链表指定位置插入
		// 
	//void SingleListErase();//单链表指定位置删除
		// 
	//SGLN* SingleListFind();//单链表查找元素
		//先断言链表是否为空，为空则不执行
		//否则从第一个结构体依次查找，直到结构体地址成员为空
		//找到返回对应值所在结构体指针地址
		//否则反会空指针
	//void SingleListDestory();//单链表动态内存空间销毁
		// 
	//void SingleListInit();//单链表初始化
		// 